//
//  GLESPointSprite.m
//  PointSprite
//
//  Created by 畑圭輔 on 10/03/27.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "GLESPointSprite.h"
#import "TextureUtils.h"

@implementation GLESPointSpriteBase

- (id) initWithParticlesMaxNum : (NSInteger)max {
	
	_particles  = 0; // particle
	_vertices = 0; // PointSprite Vertex

	if (self = [super init]) {
		
		_particles = malloc( sizeof( Particle ) * max );
		if( !_particles ) {
			[self release];
			return nil;
		}

		_vertices = malloc( sizeof( GLESPointSprite ) * max );
		if( !_vertices ) {
			[self release];
			return nil;
		}
		
		bzero( _particles , sizeof( Particle ) * max );
		bzero( _vertices  , sizeof( GLESPointSprite ) * max );
		
		_particleMax		 = max;
		_activeParticleIndex = 0;
		
		// Particle Buffer
		glGenBuffers(1, &_verticesID);
		
		glBindBuffer(GL_ARRAY_BUFFER, _verticesID);
		glBufferData(GL_ARRAY_BUFFER, sizeof(GLESPointSprite)*_particleMax, _vertices, GL_DYNAMIC_DRAW);
		glBindBuffer(GL_ARRAY_BUFFER, 0);		
	}
	return self;
}

- (void) updateParticle : (Particle *)particle {

	// アクティブなパーティクルを先頭から詰めていく
	_vertices[ _activeParticleIndex ].colors = particle->color;
	_vertices[ _activeParticleIndex ].pos.x  = particle->pos.x;
	_vertices[ _activeParticleIndex ].pos.y  = particle->pos.y;
	_vertices[ _activeParticleIndex ].size   = particle->size;
}

- (void) presentParticles {

	// 作成した頂点バッファをバインド
	glBindBuffer(GL_ARRAY_BUFFER, _verticesID);
	// 更新した頂点データを転送
	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLESPointSprite)*_particleMax, _vertices);
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

- (void) draw {
	
	// Point Spriteでは、テクスチャ座標を無効にする
	glEnableClientState( GL_VERTEX_ARRAY );
	glEnableClientState( GL_COLOR_ARRAY);
	glEnable( GL_TEXTURE_2D );
	glEnable( GL_BLEND );
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	// TextureUtilsを使って、カレントのバインドテクスチャ番号を変更
	[TextureUtils bindTexture2D:_texture];
	
	glEnable(GL_POINT_SPRITE_OES);
	glTexEnvi( GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE );	
	
	glBindBuffer(GL_ARRAY_BUFFER, _verticesID);
	
	// 頂点情報
	glVertexPointer(2,GL_FLOAT,sizeof(_vertices[0]),0);
	
	// カラー情報ポインタ
	glColorPointer(4, GL_FLOAT, sizeof(_vertices[0]),(GLvoid*) offsetof(GLESPointSprite,colors) );
	
	// ポイントスプライトのサイズの設定
	glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
	glPointSizePointerOES(GL_FLOAT,sizeof(_vertices[0]),(GLvoid*) offsetof(GLESPointSprite,size) );
	
	// ブレンド設定
	GLuint blend_s = GL_SRC_ALPHA;
	GLuint blend_d = GL_ONE_MINUS_SRC_ALPHA;
	glBlendFunc( blend_s, blend_d );
	
	// 現在有効なパーティクルの数を描画
	// drawまでにインクリメントされた _activeParticleIndex = 描画数
	glDrawArrays(GL_POINTS, 0, _activeParticleIndex);
	
	// 元に戻す
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
	glDisable(GL_POINT_SPRITE_OES);
	
	// テクスチャ座標を有効にする
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState( GL_VERTEX_ARRAY );
	glDisableClientState( GL_COLOR_ARRAY);
	glDisable( GL_TEXTURE_2D );
	glDisable( GL_BLEND );
}

- (void) dealloc {

	if( _particles )
		free(_particles);
	if( _vertices )
		free(_vertices);

	_particleMax = 0;

	glDeleteBuffers(1, &_verticesID);
	
	[super dealloc];
}

@end
